/**
 * 命令行服务器
 * 张勇 41204@qq.com
 */

#pragma once

#include <stdint.h>
#include <string.h>

#include "std_err.h"
#include "unios.h"
#include "transceiver.h"

#ifdef __cplusplus
extern "C" {
#endif

/// 返回值最大长度
#define CONSOLE_ACK_SIZE_MAX 256

// forwards
typedef struct _console console_t;

/// @brief 命令-处理函数映射
typedef struct {
    // 命令
	const char *cmd;
    // 命令处理函数
	void (*handler)(console_t* con, const char *cmd, const char *params);
    // 指令用法/帮助
	const char *usage;
} console_cmd_map_t;

/// @brief 命令行描述结构
typedef struct _console {
	/// @brief 用于通信的 收发器
	transceiver_t *trx;
	/// @brief 命令映射表
	const console_cmd_map_t* cmds;
	/// @brief 命令行提示符
	const char *prompt;
	/// @brief 当控制台接收到一个完整命令, 用于 @see unios_task_run_on_rx_msg() 的消息回调函数，类型见 @see unios_task_rxmsg_handler_t
	uint8_t rxmsgtype;
	/// @brief 接收数据缓冲区(由用户分配并提供)
	uint8_t* rxbuf;
	/// @brief 接收数据缓冲区大小
	uint16_t rxbufsize;
	/// @brief 接收数据缓冲区当前数据长度
	uint16_t rxlen;

	/// @brief 文件传输事务信息
	struct {
		uint32_t mtu;		// 传输 MTU
		uint32_t win;		// 传输 WIN
		unios_file_t uf;	// 要传输的文件句柄
		uint32_t fsize;		// 文件大小
		uint32_t fpos;		// 已传输的大小
		uint32_t frmsn;		// 帧序号
	} fts;
} console_t;

/// @brief 控制台在 transceiver_t 上开始监听
std_err_t console_listen_on(console_t* con, transceiver_t *trx);

/// @brief 当控制台接收到一个字符
void console_on_rx_char(console_t* con, char ch);
/// @brief 当控制台接收到一个完整命令, 用于 @see unios_task_run_on_rx_msg() 的消息回调函数，类型见 @see unios_task_rxmsg_handler_t
void console_on_rx_command(void* cookie, void* receiver, size_t len, void* data);

/// @brief 控制台输出
static inline size_t console_puts(console_t* con, const char* str) { size_t txlen = 0; return con->trx->tx(con->trx, str, strlen(str), &txlen) ? 0 : txlen; }
/// @brief 控制台格式化输出
size_t console_printf(console_t* con, const char* format, ...);

/// @brief 在控制台打印指令帮助
/// @param cmd 要打印帮助的指令名称；为 NULL 打印所有指令帮助
void console_print_help(console_t* con, const char* cmd);

/// @brief 处理要接收的文件信息
/// @param 指令格式: FILEDN mtu,win,fsize,device_path\r\n
/// @param 指令示例: FILEDN 4096,1,1000000,/iflash/sector11\r\n
/// @return 正常应答格式: OK:mtu,win\r\n
/// @return 正常应答示例: OK:1024,1\r\n
/// @exception 异常应答格式: ERROR: error message\r\n
/// @exception 异常应答示例: ERROR: Invalid path !\r\n
void console_cmd_rxfileinfo(console_t* con, const char *cmd, const char *params);

/// @brief 处理接收文件数据
/// @param 指令格式: DATADN frmsn,frmlen,frmsum\r\n
/// @param 指令示例: DATADN 35,1024,3752\r\n
/// @return 正常应答格式: OK:fsn\r\n
/// @return 正常应答示例: OK:35\r\n
/// @exception 异常应答格式: ERROR: error message\r\n
/// @exception 异常应答示例: ERROR: Invalid frame SN !\r\n
void console_cmd_rxfiledata(console_t* con, const char *cmd, const char *params);

#ifdef __cplusplus
}
#endif
